﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Text.RegularExpressions;
using System.IO;
using System.Runtime.InteropServices;
using log4net;
using System.Windows.Forms.DataVisualization.Charting;
using System.Net.NetworkInformation;
using System.Threading;
using System.Diagnostics;

namespace DomainName
{
    public partial class Form1 : Form
    {
        private delegate void ThreadAccessRTB(string message);
        private ThreadAccessRTB setStatus = null;
        private delegate void UpdateAccessChartDelegate();
        private UpdateAccessChartDelegate setChart = null;
        private delegate void SetNetinformationDelegate(string message);
        private SetNetinformationDelegate setNetInformation = null;
        private string defaultUrl = "http://www.baidu.com";
        private bool startStatus;
        private int recordNumber = 1000;
        private int recordCurrentNumber = 0;
        private object lck = new object();
        log4net.ILog log = null;
        private long[] pingTime = new long[24 * 60 * 60];
        private string distance = "";
        private long currentYMAX = 0;
        /// <summary>
        /// 最大允许网络延迟
        /// </summary>
        private const long MAX_DELAY = 1000;
        private const long MIN_DELAY = 50;
        public Form1()
        {
            InitializeComponent();
            BeginPaint();
            setStatus = new ThreadAccessRTB(ThreadAccessRTBFromOther);
            setChart = new UpdateAccessChartDelegate(UpdateAccessLineChart);
            setNetInformation = new SetNetinformationDelegate(SetNetinformationForLabel);
            startStatus = false;
            SetNetWorkColor(false);
            log = log4net.LogManager.GetLogger("DomainName.Logging");
            Thread threadForNetInformation = new Thread(new ThreadStart(GetNetInformationThread));
            threadForNetInformation.Start();
            //string filePath = AppDomain.CurrentDomain.BaseDirectory;
            chartAccessLine.Legends.Clear();
            chartAccessLine.ChartAreas.Clear();
            chartAccessLine.AntiAliasing = AntiAliasingStyles.None;
            chartAccessLine.BorderSkin.SkinStyle = BorderSkinStyle.None;
            chartAccessLine.BorderlineDashStyle = ChartDashStyle.NotSet;
            chartAccessLine.BackColor = Color.White;
            chartAccessLine.Width = 713;
            chartAccessLine.Height = 326;
            chartAccessLine.ChartAreas.Add("AccessLineArea");
            chartAccessLine.ChartAreas["AccessLineArea"].AxisX.Maximum = 24;
            chartAccessLine.ChartAreas["AccessLineArea"].AxisX.Minimum = 0;
            chartAccessLine.ChartAreas["AccessLineArea"].AxisX.Interval = 2;
            chartAccessLine.ChartAreas["AccessLineArea"].AxisY.Maximum = 50;
            chartAccessLine.ChartAreas["AccessLineArea"].AxisY.Minimum = 0;
            chartAccessLine.ChartAreas["AccessLineArea"].AxisX.MajorGrid.Enabled = false;
            chartAccessLine.ChartAreas["AccessLineArea"].AxisX.MajorTickMark.Enabled = false;
            chartAccessLine.ChartAreas["AccessLineArea"].AxisX.MinorGrid.Enabled = true;
            chartAccessLine.ChartAreas["AccessLineArea"].AxisX.MinorTickMark.Enabled = false;
            chartAccessLine.ChartAreas["AccessLineArea"].AxisX.MinorGrid.LineDashStyle = ChartDashStyle.DashDot;
            chartAccessLine.ChartAreas["AccessLineArea"].AxisY.MajorGrid.Enabled = false;
            chartAccessLine.ChartAreas["AccessLineArea"].AxisY.MajorTickMark.Enabled = false;
            chartAccessLine.ChartAreas["AccessLineArea"].AxisY.MinorGrid.Enabled = true;
            chartAccessLine.ChartAreas["AccessLineArea"].AxisY.MinorTickMark.Enabled = false;
            chartAccessLine.ChartAreas["AccessLineArea"].AxisY.MinorGrid.LineDashStyle = ChartDashStyle.DashDotDot;
            chartAccessLine.ChartAreas["AccessLineArea"].Position.X = 0;
            chartAccessLine.ChartAreas["AccessLineArea"].Position.Y = 0;
            chartAccessLine.ChartAreas["AccessLineArea"].Position.Width = 96;
            chartAccessLine.ChartAreas["AccessLineArea"].Position.Height = 96;
            chartAccessLine.ChartAreas["AccessLineArea"].InnerPlotPosition.X = 4;
            chartAccessLine.ChartAreas["AccessLineArea"].InnerPlotPosition.Y = 4;
            chartAccessLine.ChartAreas["AccessLineArea"].InnerPlotPosition.Width = 95;
            chartAccessLine.ChartAreas["AccessLineArea"].InnerPlotPosition.Height = 92;
            chartAccessLine.ChartAreas["AccessLineArea"].CursorX.AutoScroll = true;
            chartAccessLine.ChartAreas["AccessLineArea"].CursorX.LineColor = Color.Red;
            chartAccessLine.ChartAreas["AccessLineArea"].CursorX.LineDashStyle = ChartDashStyle.Solid;
            chartAccessLine.ChartAreas["AccessLineArea"].CursorX.LineWidth = 1;
            chartAccessLine.ChartAreas["AccessLineArea"].CursorX.SelectionColor = Color.FromArgb(0, 98, 0);
            chartAccessLine.ChartAreas["AccessLineArea"].CursorX.IntervalType = DateTimeIntervalType.Milliseconds;
            chartAccessLine.ChartAreas["AccessLineArea"].CursorY.AutoScroll = true;
            chartAccessLine.ChartAreas["AccessLineArea"].CursorY.LineColor = Color.Red;
            chartAccessLine.ChartAreas["AccessLineArea"].CursorY.LineDashStyle = ChartDashStyle.Solid;
            chartAccessLine.ChartAreas["AccessLineArea"].CursorY.LineWidth = 1;
            chartAccessLine.ChartAreas["AccessLineArea"].CursorY.SelectionColor = Color.FromArgb(0, 98, 0);
            chartAccessLine.ChartAreas["AccessLineArea"].CursorY.IntervalType = DateTimeIntervalType.Milliseconds;
            chartAccessLine.ChartAreas["AccessLineArea"].CursorX.IsUserEnabled = true;
            chartAccessLine.ChartAreas["AccessLineArea"].CursorX.IsUserSelectionEnabled = true;
            chartAccessLine.ChartAreas["AccessLineArea"].CursorY.IsUserEnabled = true;
            chartAccessLine.ChartAreas["AccessLineArea"].CursorY.IsUserSelectionEnabled = true;
            //chartAccessLine.Legends.Add("Delay");LineDashStyle
            chartAccessLine.Series.Add("AccessLine");
            chartAccessLine.Series["AccessLine"].ChartArea = "AccessLineArea";
            chartAccessLine.Series["AccessLine"].ChartType = SeriesChartType.FastLine;
            chartAccessLine.Series["AccessLine"].Color = Color.Green;
            //chartAccessLine.Series["AccessLine"].Legend = "Delay";
            //chartAccessLine.Series["AccessLine"].LegendText = "延迟(ms)";
            chartAccessLine.Series["AccessLine"].EmptyPointStyle.BorderWidth = 0;
            chartAccessLine.Series["AccessLine"].EmptyPointStyle.MarkerStyle = MarkerStyle.None;
            //chartAccessLine.Legends["Delay"].BackColor = Color.FromArgb(255, 255, 255);

            //图表点信息提示
            chartAccessLine.GetToolTipText += chartAccessLine_GetToolTipText;


            //图表鼠标位置更新事件
            chartAccessLine.CursorPositionChanged += chartAccessLine_CursorPositionChanged;
            chartAccessLine.CursorPositionChanging += chartAccessLine_CursorPositionChanging;
            //初始化图表

        }

        void chartAccessLine_CursorPositionChanging(object sender, CursorEventArgs e)
        {
            DisplayDataPosition(e.Axis, e.NewPosition);
        }

        void chartAccessLine_CursorPositionChanged(object sender, CursorEventArgs e)
        {
            DisplayDataPosition(e.Axis, e.NewPosition);
        }
        private void DisplayDataPosition(Axis axis, double position)
        {
            if (double.IsNaN(position))
            {
                return;
            }
            if (axis.AxisName == AxisName.X)
            {
                lblMarkX.Text ="X:"+String.Format("{0:0.0000}",position);
            }
            if (axis.AxisName == AxisName.Y)
            {
                lblMarkY.Text ="Y:"+ String.Format("{0:0.0000}", position);
            }
        }

        void chartAccessLine_GetToolTipText(object sender, ToolTipEventArgs e)
        {
            switch (e.HitTestResult.ChartElementType)
            {
                case ChartElementType.DataPoint:
                    {
                        int cursurIndex = e.HitTestResult.PointIndex;
                        if (cursurIndex > -1)
                        {
                            
                        }
                    }; break;
            }
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            if (!String.IsNullOrWhiteSpace(textBox1.Text) && textBox1.Text.Trim().ToLower() != "http://")
            {
                defaultUrl = textBox1.Text;
            }
            SetStartStatus();
        }
        private void StartRequestDomainName(string url)
        {
            Regex reg = new Regex(@"http://\w+.\w+.\w+");
            if (reg.IsMatch(url))
            {
                try
                {
                    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                    request.GetResponse();
                    string domainName = request.Headers["Host"];
                    request.Abort();
                    if (url.EndsWith(domainName))
                    {
                        SetLogInformation("目标域名：" + defaultUrl + ",返回域名：" + domainName + ",域名访问状态：True", true);
                    }
                    else
                    {
                        SetLogInformation("目标域名：" + defaultUrl + ",返回域名：" + domainName + ",域名访问状态：Error", false);
                    }

                }
                catch (WebException webError)
                {

                }
                catch (Exception ex)
                {

                }
            }
            else
            {
                MessageBox.Show("请输入正确的域名", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
        private void SetStartStatus()
        {
            if (startStatus)
            {
                startStatus = false;
                btnStart.Text = "(&S)开始";
                timer1.Stop();
                timer2.Stop();
                textBox1.Enabled = true;
            }
            else
            {
                startStatus = true;
                timer1.Start();
                timer2.Start();
                textBox1.Enabled = false;
                btnStart.Text = "(&S)停止";
            }
        }
        [DllImport("user32")]
        private static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, IntPtr lParam);
        private const int WM_SETREDRAW = 0xB;
        private void BeginPaint()
        {
            SendMessage(rtbDetailInformation.Handle, WM_SETREDRAW, 0, IntPtr.Zero);
        }
        private void EndPaint()
        {
            SendMessage(rtbDetailInformation.Handle, WM_SETREDRAW, 1, IntPtr.Zero);
            rtbDetailInformation.Refresh();
        }

        private void SetLogInformation(string message, bool status)
        {
            rtbDetailInformation.Invoke(setStatus, new object[] { message });
            SetNetWorkColor(status);

        }
        private void UpdateDisplayChart()
        {
            chartAccessLine.Invoke(setChart);
        }
        private void ThreadAccessRTBFromOther(string message)
        {
            string temp = "Log=>时间：" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff") + "," + message + Environment.NewLine;
            rtbDetailInformation.AppendText(temp);
            log.Info(temp);
            recordCurrentNumber++;
            if (temp.Contains("True"))
            {
                rtbDetailInformation.Select(rtbDetailInformation.Text.LastIndexOf("True"), 4);
                rtbDetailInformation.SelectionColor = Color.Green;
            }
            if (temp.Contains("Error"))
            {
                rtbDetailInformation.Select(rtbDetailInformation.Text.LastIndexOf("Error"), 5);
                rtbDetailInformation.SelectionColor = Color.Red;
            }
            rtbDetailInformation.SelectionStart = rtbDetailInformation.Text.Length;
            rtbDetailInformation.Select();
            EndPaint();
            if (recordCurrentNumber == recordNumber)
            {
                rtbDetailInformation.ResetText();
                GC.Collect();
            }
        }
        private void SetNetWorkColor(bool netStatus)
        {
            if (netStatus)
            {
                tsLblColor.BackColor = Color.Green;
                tsLblNetWorkStatus.Text = "    网络访问正常";
            }
            else
            {
                tsLblColor.BackColor = Color.Red;
                tsLblNetWorkStatus.Text = "    网络访问异常";
            }
        }
        private void timer1_Tick(object sender, EventArgs e)
        {
            StartRequestDomainName(defaultUrl.ToLower());
        }
        private void UpdateAccessLineChart()
        {
            UpdateAccessLineData(defaultUrl.ToLower());
        }
        private void GenerateTestData()
        {

        }
        private void UpdateAccessLineData(string url)
        {
            int index = GetTimeIndex();
            pingTime[index] = GetRoundtripTime(url);
            if (pingTime[index] > currentYMAX)
            {
                currentYMAX = pingTime[index];
            }
            chartAccessLine.ChartAreas["AccessLineArea"].AxisY.Maximum = GetAxisYMax(currentYMAX);
            chartAccessLine.Series["AccessLine"].Points.AddXY(index / (24 * 60 * 60f) * 24, pingTime[index]);
            chartAccessLine.Invalidate();
        }
        private long GetAxisYMax(long yValue)
        {
            long max = MIN_DELAY;
            if (yValue > 50)
            {
                if (yValue <= 100)
                {
                    max = 100;
                }
                else if (yValue > 100 && yValue <= 150)
                {
                    max = 150;
                }
                else if (yValue > 150 && yValue <= 200)
                {
                    max = 200;
                }
                else if (yValue > 200 && yValue <= 250)
                {
                    max = 250;
                }
                else if (yValue > 250 && yValue <= 300)
                {
                    max = 300;
                }
                else if (yValue > 300 && yValue <= 400)
                {
                    max = 400;
                }
                else if (yValue > 400 && yValue <= 500)
                {
                    max = 500;
                }
                else
                {
                    max = MAX_DELAY;
                }
            }
            return max;
        }
        /// <summary>
        /// 获取指定域名的IPAddress
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        private IPAddress GetIPAddress(string url)
        {
            Regex reg = new Regex(@"http://\w+.\w+.\w+");
            if (reg.IsMatch(url))
            {
                IPAddress[] address = Dns.GetHostAddresses(url);
                if (address.Length <= 0)
                {
                    return null;
                }
                else
                {
                    return address[0];
                }
            }
            else
            {
                return null;
            }
        }
        private long GetRoundtripTime(IPAddress remoteAddress)
        {
            try
            {
                Ping ping = new Ping();
                PingReply reply = ping.Send(remoteAddress);
                if (reply.Status == IPStatus.Success)
                {
                    return reply.RoundtripTime;
                }
                else
                {
                    return MAX_DELAY;
                }
            }
            catch (Exception ex)
            {
                return MAX_DELAY;
            }
        }
        private long GetRoundtripTime(string remoteName)
        {
            Regex reg = new Regex(@"http://\w+.\w+.\w+");
            if (reg.IsMatch(remoteName))
            {
                try
                {
                    Ping ping = new Ping();
                    PingReply reply = ping.Send(remoteName.Replace("http://", ""));
                    if (reply.Status == IPStatus.Success)
                    {
                        return reply.RoundtripTime;
                    }
                    else
                    {
                        return MAX_DELAY;
                    }
                }
                catch (Exception ex)
                {
                    return MAX_DELAY;
                }
            }
            else
            {
                return MAX_DELAY;
            }
        }
        private int GetTimeIndex()
        {
            DateTime currentTime = DateTime.Now;
            return currentTime.Hour * 60 * 60 + currentTime.Minute * 60 + currentTime.Second;
        }

        private void timer2_Tick(object sender, EventArgs e)
        {
            UpdateAccessLineChart();
        }
        private IPModel model = null;
        private string outIP = string.Empty;
        /// <summary>
        /// 公网IP接口：http://www.net.cn/static/customercare/yourIP.asp
        /// IP查询接口:http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=json&ip=
        /// </summary>
        private void GetJSON()
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.net.cn/static/customercare/yourIP.asp");
            WebResponse response = request.GetResponse();
            using (StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
            {
                Regex regex = new Regex(@"\d\d{1,2}.\d{1,3}.\d{1,3}.\d{1,3}");
                string urlResponse = sr.ReadToEnd();
                outIP = regex.Match(urlResponse).Value;
                request.Abort();
                string detailInformatinoRequest = "http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=json&ip=" + outIP;
                HttpWebRequest detailRequest = (HttpWebRequest)WebRequest.Create(detailInformatinoRequest);
                WebResponse detailResponse = detailRequest.GetResponse();
                using (StreamReader srDetail = new StreamReader(detailResponse.GetResponseStream(), Encoding.UTF8))
                {
                    string detailInformationJSON = srDetail.ReadToEnd();
                    model = Json.GetJSONDeserialize<IPModel>(detailInformationJSON);
                    //string temp = detailInformationJSON.Replace(@"\\", @"\");
                    //string detailInformationDeal = System.Net.WebUtility.HtmlDecode(detailInformationJSON.Replace(@"\\",@"\"));
                    //string hasDealed=  server.HtmlDecode(detailInformationJSON);
                    //model.GetIPDetail();
                    detailRequest.Abort();
                }
            }
        }
        private void SetNetinformation(string netInformation)
        {
            lblNetworkInformation.Invoke(setNetInformation, netInformation);
        }
        private void SetNetinformationForLabel(string message)
        {
            lblNetworkInformation.Text = message;
        }
        private void GetNetInformationThread()
        {
            GetJSON();
            if (model != null)
            {
                SetNetinformation(model.GetIPDetail());
            }
        }

        private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (tabControl1.SelectedTab.Name == "tabPage2")
            {
                if (!String.IsNullOrEmpty(outIP))
                {
                    lblYourIP.Text = outIP;
                }
            }
        }

        private void btnReport_Click(object sender, EventArgs e)
        {

        }
    }
}
